

$$.Geo = new function () {
	var me = this;
    var Addr = null, LastAddr = null;
    
	var dftAddr = {
		unloc: true,//定位失败后的默认地址
		gps: { lat: 39.929986, lng: 116.395645 },
		map: { "Busi": "景山,地安门,沙滩", "City": "北京市", "County": "东城区", "Prov": "北京市", "Street": "东板桥大街22号", "Code": 131 },
		prov: 110000,
		city: 110100,
		county: 110101
    };
    me.DftAddr = function(){return dftAddr;};

	me.DispDist = function (dist) {
		if (dist === 0) return "0m";
		if (!dist || dist < 0) return "";
		if (dist < 1000) return Math.round(dist) + "m";
		dist = dist / 1000;
		if (dist >= 10) return dist.toFixed(0) + "km";
		return dist.toFixed(1) + "km";
	};
	me.CalcDist = function (lat1, lng1, lat2, lng2) {
		if (!lat1 || !lng1 || !lat2 || !lng2) return null;
		var lat = (lat2 - lat1) * Math.PI / 180;
		var lng = (lng2 - lng1) * Math.PI / 180;
		lat1 = lat1 * Math.PI / 180;
		lat2 = lat2 * Math.PI / 180;
		lat = Math.sin(lat / 2);
		lng = Math.sin(lng / 2);
		var a = lat * lat + Math.cos(lat1) * Math.cos(lat2) * lng * lng;
		var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
		return 6371000 * c;
	};

	//获取指定经纬度的地理信息
	//gps：{lat,lng}
	function BaiduAddr(lat, lng, callback) {
		var url = "http://api.map.baidu.com/geocoder/v2/?ak=vN0BFcVu0YUeFxM00SU5OLwM&output=json&coordtype=wgs84ll&location=";
		url += lat + "," + lng;
		function parse(data) {
			if (!data || !data.result) { return null; }
			var rst = data.result.addressComponent
			var addr = {
				gps: { lat: lat, lng: lng },
				map: {
					Prov: rst.province,
					City: rst.city,
					Code: data.result.cityCode,
					County: rst.district,
					Street: (rst.street + rst.street_number) || data.result.sematic_description
				}
			};
			return addr;
		}
		function get(num) {
			var called = false;
			if (num < 0) num = 0;
			num++;
			function repeat()
			{
				if (num < 3) get(num);
				else callback();
			}
			$.ajax({
				method: "POST",
				url: url,
				dataType: "jsonp",//text
				success: function (text) {
					called = true;
					var dat = $$.Jsonar.parse(text);
					if (!dat) { repeat(); return; }
					callback(parse(dat));
				},
				error: function (a, b, err) { called = true; repeat(); console.error(err); },
				complete: function () { if (!called) repeat(); },
				async: true,
				cache: false,
				global: false
			});
		}
		get();
	}

	var callbacks = [], realbacks = [];
	function Backcalls(adr) {
		var addr = adr || Addr || LastAddr;
		while (callbacks.length > 0) {
			var cbk = callbacks.pop();
			if (cbk) cbk(addr);
        }
        if(adr !== 0 && !adr) return;
		while (realbacks.length > 0) {
			var cbk = realbacks.pop();
			if (cbk) cbk(adr);
		}
	}

	function locArea(addr, dict) {
		if (!addr.map || !addr.map.Code || !dict.baidus) return false;
		var row = dict.baidus[""+addr.map.Code];
		if (!row) return false;
		var id = row.ID;
		if (id % 10000 === 0) return false;
		if (id % 100 === 0) {
			addr["city"] = row.ID;
			addr["prov"] = (row.parentRow || {}).ID;
			addr["county"] = (findCounty(addr.map.County, row) || {}).ID;
		}
		else {
			addr["county"] = row.ID;
			addr["city"] = (row.parentRow || {}).ID;
			addr["prov"] = ((row.parentRow ? row.parentRow.parentRow : null) || {}).ID;
		}
		return true;
	}
	function findCounty(cn, city) {
		if (!cn || !city.childRows) return null;
		var ns = {};
		for (var i in city.childRows) {
			var row = city.childRows[i];
			if (!row || !row.Name) continue;
			if (cn === row.Name) return row;
			ns[row.Name] = row;
		}
		for (var len = cn.length - 1; len > 0; len--) {
			cn = cn.substr(0, len);
			for (var n in ns) {
				if (n.length < len) continue;
				n = n.substr(0, len);
				if (n === cn) return ns[n];
			}
		}
		return null;
    }

    function gotGps (rst, lat, lng) {
        if (rst !== true) { 
            Backcalls(0); 
            if(rst) $$.Tips(rst, 5);
            return; 
        }
        BaiduAddr(lat, lng, function (addr) {
            if (!addr) { Backcalls(0); return; }
            $$.GetDict("area", function (dict) {
                if (!dict) { Backcalls(0); return; }
                if (!locArea(addr, dict)) { Backcalls(0); $$.Tips("未定位到城市", 5); }
                else {
                    Addr = addr;
                    Backcalls(addr);
                    $$.DB.SetLocal("app", "geo.addr", addr, 200);
                }
            });
        });
    }

    var geo = navigator.geolocation;
    var schema = (location.protocol || "").toLowerCase();
    function getGps(){
        if ($$Shell.Gps === 1) { 
            var guid = $$.Shell._addCallback(gotGps);
            $$.Shell._exec("Gps", null, guid);
            return;
         }
         
         if (!geo) { gotGps("不能定位"); return; }
         if (schema !== "https" && schema !== "https:") { gotGps("不能定位"); return; }
         geo.getCurrentPosition(
             function (pos) {
                 if (!pos) { gotGps("定位无效"); return; }
                 pos = pos.coords;
                 if (!pos) { gotGps("定位无效"); return; }
                 gotGps(true, pos.latitude, pos.longitude );
             },
             function (err) {
                 var msg = "定位失败";
                 if (err.code === err.PERMISSION_DENIED) msg = "您拒绝定位！\n本应用需根据您的地理位置更好的提供服务";
                 else if (err.code === err.POSITION_UNAVAILABLE) msg = "无法定位";
                 else if (err.code === err.TIMEOUT) msg = "定位超时";
                 gotGps(msg);
             },
             { timeout: 10000, maximumAge: 600000 }
         );
    }

	//获取实时位置的地理信息，不能定位时返回null
	me.GetRealAddr = function (callback) {
		if (callback) realbacks.push(callback);
        getGps();
	};

	//获取当前位置的地理信息，从缓存获取后再实时定位，没有时返回默认位置
	me.GetAddr = function (callback, refresh) {
        if(refresh === true) {
            if (callback) realbacks.push(callback);
            getGps();
            return;
        }
		if(callback) callbacks.push(callback);
        if (Addr) { Backcalls(); return; }
        $$.DB.GetLocal("app", "geo.addr", function (addr) {
            if (addr) { LastAddr = addr; Backcalls(); }
        });
        getGps();
	};
};